package ch.zhaw.skuh.turing.model.turingmaschine;



public abstract class Turing {
	
	//static variables for righ-left moves (for short-hand notation)
	protected static final int L = -1;
	protected static final int R = -1;
	
	private final int maxState;
	private final int alphabetLength;
	private final int[] acceptState;
	private final int tapeCount;
	private final String name;
	private Maschine maschine;
		
	// this class does NOT deal with characters, only with index-positions in alphabet !!!
	// blank must be in first position of alphabet!!
	protected Turing(int maxState, int alphabetLength, int[] acceptState, int tapeCount,
			String name) {
		this.maxState = maxState;
		this.alphabetLength = alphabetLength;
		checkAcceptState(acceptState);
		this.acceptState = acceptState;
		this.name = name;
		this.tapeCount = tapeCount;
	}
	
	//checks
	private void checkAcceptState(int[] acceptState) {
		// check acceptState-states
		for (int i = 0; i < acceptState.length; i++) {
			if (maxState <= acceptState[i]) {
				throw new IndexOutOfBoundsException();
			}
		}
	}

	// other info-functions
	public final boolean isAccepted(int state) {
		if (state >= maxState) {
			throw new IndexOutOfBoundsException();
		}
		for (int i = 0; i < acceptState.length; i++) {
			if (acceptState[i] == state) {
				return true;
			}
		}
		return false;
	}

	// get/set functions
	public final int getMaxState() {
		return maxState;
	}
	
	public final int getAlphLength(){
		return alphabetLength;
	}

	public final int getTapeCount() {
		return tapeCount;
	}

	public final String getName() {
		return name;
	}
	
	protected final void setTapes(int[][] input, int[] pos, int startState){
		maschine = null;
		maschine = new Maschine(this, input, pos, startState);
	}

	public final Maschine getMaschine() {
		return maschine;
	}
	
	// not advisable for large rule-sets (large alphabets or many tapes) !!!
	public abstract boolean isOutputEnabled();
	
	public final boolean doStep(){
		return this.maschine.doSaveStep();
	}
	
	public final int[] getPositions(){
		int[] ret = new int[getTapeCount()];
		for(int i=0;i<ret.length;i++){
			ret[i]=maschine.getPosition(i);
		}
		return ret;
	}
}
